/**
 * 
 */
package edu.ucr.cs.dblab.acestore.base.datatypes;

import java.io.ByteArrayOutputStream;
import java.io.DataInput;
import java.io.DataOutput;
import java.io.DataOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * An implementation of serializing/deserializing the integer
 * data type. 
 * 
 * The algorithm for binary serializing/deserializing is from
 * the Integer data type implementation from the Hyracks 
 * project: IntegerSerializerDeserializer.java.
 * 
 * @author jarod
 * @created Jan 11, 2011
 */
public class IntegerSerDeserializer implements ISerDeserializer<Integer> {

	private IntegerSerDeserializer(){};
	
	private static class SingletonHolder {
		public static final IntegerSerDeserializer INSTANCE = new IntegerSerDeserializer();
	}
	
	public static IntegerSerDeserializer getSingleton(){
		return SingletonHolder.INSTANCE;
	}
	
	@Override
	public Integer deserialize(ByteBuffer buf, int offset, int length) throws IOException {
		return deserialize(buf.array(), offset, length);
	}

	@Override
	public Integer deserialize(byte[] buf, int offset, int length) throws IOException {
		return ((buf[offset] & 0xff) << 24) + ((buf[offset + 1] & 0xff) << 16) + ((buf[offset + 2] & 0xff) << 8) + ((buf[offset + 3] & 0xff) << 0);
	}

	@Override
	public byte[] serialize(Integer data) throws IOException {
		ByteArrayOutputStream bout = new ByteArrayOutputStream();
		DataOutputStream out = new DataOutputStream(bout);
		out.writeInt(data);
		return bout.toByteArray();
	}

	@Override
	public Integer deserialize(DataInput in) throws IOException {
		return in.readInt();
	}
	
	public static int DESERIALIZE(byte[] buf, int offset){
		return ((buf[offset] & 0xff) << 24) + ((buf[offset + 1] & 0xff) << 16) + ((buf[offset + 2] & 0xff) << 8) + ((buf[offset + 3] & 0xff) << 0);
	}

	@Override
	public void serialize(Integer data, DataOutput out) throws IOException {
		out.writeInt(data);
	}
	
	public static byte[] SERIALIZE(int value) {
		return new byte[] {
                (byte)(value >>> 24),
                (byte)(value >>> 16),
                (byte)(value >>> 8),
                (byte)value};
	}

	@Override
	public int getTypeIndex() {
		return 0;
	}

	@Override
	public int compare(byte[] b1, int s1, int l1, byte[] b2, int s2, int l2) throws IOException {
		int value1 = deserialize(b1, s1, l1);
		int value2 = deserialize(b2, s2, l2);
		return compare(value1, value2);
	}

	@Override
	public int compare(Integer value1, Integer value2) {
		return value1.compareTo(value2);
	}

	@Override
	public int getTypeSize() {
		return Integer.SIZE / 8;
	}

    @Override
    public Integer deserialize(String str) throws IOException {
        return Integer.valueOf(str);
    }

    @Override
    public byte[] serialize(String str) throws IOException {
        int value = deserialize(str);
        return new byte[] {
                (byte)(value >>> 24),
                (byte)(value >>> 16),
                (byte)(value >>> 8),
                (byte)value};
    }

}
